import React, { useEffect, useMemo, useRef, useState } from 'react';

/**
 * A lightweight virtual list for fixed row height.
 *
 * Props:
 * - height: number | string      // container height (px or CSS string)
 * - itemCount: number            // total items
 * - rowHeight: number            // fixed row height (px)
 * - overscan?: number            // extra rows to render above/below
 * - renderItem: (index) => ReactNode | ({ index, style }) => ReactNode
 * - onReachEnd?: () => void      // called when near bottom
 * - reachEndThreshold?: number   // px from bottom to trigger onReachEnd (default 200)
 * - className?: string
 * - style?: React.CSSProperties
 */
function VirtualList({
  height,
  itemCount,
  rowHeight,
  overscan = 4,
  renderItem,
  onReachEnd,
  reachEndThreshold = 200,
  className,
  style
}) {
  const containerRef = useRef(null);
  const [scrollTop, setScrollTop] = useState(0);

  const containerHeight = useMemo(() => {
    if (typeof height === 'number') return height;
    return undefined; // will rely on CSS height
  }, [height]);

  const totalHeight = itemCount * rowHeight;

  const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
  const endIndex = Math.min(
    itemCount - 1,
    startIndex + Math.ceil(((containerHeight || 0) || window.innerHeight) / rowHeight) + overscan * 2
  );
  const visibleItems = [];
  for (let i = startIndex; i <= endIndex; i++) {
    const top = i * rowHeight;
    const itemStyle = {
      position: 'absolute',
      top: top,
      left: 0,
      right: 0,
      height: rowHeight
    };
    // Support both signatures: renderItem(index) or renderItem({ index, style })
    const node = renderItem.length > 1 ? renderItem({ index: i, style: itemStyle }) : renderItem(i);
    visibleItems.push(
      <div key={i} style={itemStyle}>
        {renderItem.length > 1 ? renderItem({ index: i, style: { height: '100%' } }) : node}
      </div>
    );
  }

  const handleScroll = (e) => {
    const current = e.currentTarget;
    const top = current.scrollTop;
    setScrollTop(top);

    if (onReachEnd) {
      const distanceToBottom = totalHeight - (top + current.clientHeight);
      if (distanceToBottom <= reachEndThreshold) {
        onReachEnd();
      }
    }
  };

  useEffect(() => {
    // reset scroll when data shrinks
    if (containerRef.current && scrollTop > totalHeight) {
      containerRef.current.scrollTop = 0;
      setScrollTop(0);
    }
  }, [itemCount, totalHeight]);

  const containerStyle = {
    position: 'relative',
    overflowY: 'auto',
    height: typeof height === 'number' ? `${height}px` : height,
    ...style
  };

  return (
    <div ref={containerRef} className={className} style={containerStyle} onScroll={handleScroll}>
      <div style={{ position: 'relative', height: totalHeight }}>
        {visibleItems}
      </div>
    </div>
  );
}

export default VirtualList;




